package com.opennetexam.manager.common;

import com.openexam.openqti.openqtipaperquestion.*;
import com.openexam.openqti.qti.BaseTypeType;
import com.openexam.openqti.qti.CardinalityType;
import com.openexam.openqti.qti.CompletionStatus;
import com.openexam.openqti.qti.SessionStatusType;
import com.opennetexam.manager.dto.TestPaperOutModel;
import com.opennetexam.manager.utils.DateUtil;

import javax.xml.bind.JAXBContext;
import javax.xml.datatype.XMLGregorianCalendar;
import java.util.*;

/**
 * @author 奶茶
 * 试卷生成过程
 * Created by on 2017/11/29.
 */
public class TestPaperFromPackageGenerator {


    /**
     * 乱序试卷
     * @param testPaper
     * @param isShuffle
     * @return
     */
    public TestPaperOutModel generator(TestPaperOutModel testPaper, Boolean isShuffle, JAXBContext jcTest,JAXBContext jcItem) throws Exception {
        OpenAssessmentTest openAssessmentTest = new OpenAssessmentTest();
        openAssessmentTest.LoadFromString(testPaper.getTestString(),jcTest);

        //只有在科目和试卷都允许乱序的情况下才乱序
        if(isShuffle){
            return shuffleExamPaper(openAssessmentTest,testPaper.getQuestionDic(),isShuffle,jcItem,jcTest);
        }
        return testPaper;
    }

    /**
     * 试卷乱序
     * @param assessmentTest 试卷对象
     * @param questionList
     * @param isShuffle
     * @return
     */
    private TestPaperOutModel shuffleExamPaper(OpenAssessmentTest assessmentTest, Map<String,String> questionList,Boolean isShuffle,JAXBContext jcItem,JAXBContext jcTest) throws Exception {
        TestPaperOutModel testPaperOutModel = new TestPaperOutModel();

        //遍历试题
        for (OpenTestPart part:assessmentTest.getTestPartCollection()) {
            for (OpenAssessmentSection section:part.getAssessmentSectionCollection()) {
                if(section.isShuffle()){
                    List<OpenAssessmentItemRef> openAssessmentItemRefCollection = new ArrayList<>();

                    //判断例题数量
                    Integer exampleCount = 0;
                    for (OpenAssessmentItemRef itemRef:section.getAssessmentItemRefCollection()) {
                        if(itemRef.isExample()){
                            openAssessmentItemRefCollection.add(section.getAssessmentItemRefCollection().get(exampleCount));
                        }else{
                            break;
                        }
                    }

                    //获取随机数列
                    Integer[] itemIndexArray = OpenCombinations.showPermutations(section.getAssessmentItemRefCollection().size() - exampleCount);
                    for (int i=0;i<itemIndexArray.length;i++){
                        openAssessmentItemRefCollection.add(section.getAssessmentItemRefCollection().get(i+exampleCount));
                    }
                    section.setAssessmentItemRefCollection(openAssessmentItemRefCollection);
                }
            }  
        }
        testPaperOutModel.setQuestionDic(createExamPaperPackage(assessmentTest,questionList,isShuffle,jcItem));
        testPaperOutModel.setTestString(assessmentTest.getXmlString(jcTest));
        return testPaperOutModel;
    }

    /**
     * 乱序试题
     * @param assessmentTest
     * @param questionXmlList
     * @param isShuffle
     * @return
     */
    private Map<String,String> createExamPaperPackage(OpenAssessmentTest assessmentTest,Map<String,String> questionXmlList,Boolean isShuffle,JAXBContext jcItem) throws Exception {
        Map<String,String> questionXmlListOut = new HashMap<>();
        for (OpenTestPart testPart:assessmentTest.getTestPartCollection()) {
            for (OpenAssessmentSection section:testPart.getAssessmentSectionCollection()) {
                for (OpenAssessmentItemRef itemRef:section.getAssessmentItemRefCollection()) {
                    OpenAssessmentItem item = OpenAssessmentItem.createInstance(itemRef.getType());
                    item.LoadFromString(questionXmlList.get(itemRef.getIdentifier()),jcItem);
                    if(isShuffle){
                        questionXmlListOut.put(itemRef.getIdentifier(),item.getXmlString(jcItem));
                    }
                }
            }
        }
        return questionXmlListOut;
    }

    /**
     * 实例化 QTI 结果模型
     * @param assessmentTest
     * @param questionList
     * @return
     */
    public static OpenAssessmentResult getOpenItemResultCollection(OpenAssessmentTest assessmentTest, Map<String, String> questionList,JAXBContext jcItem) throws Exception {
        List<OpenItemResult> openItemResultList = new ArrayList<>();
        Integer sequenceIndex = 0;
        for (OpenTestPart testPart:assessmentTest.getTestPartCollection()) {
            for (OpenAssessmentSection section:testPart.getAssessmentSectionCollection()) {
                for (OpenAssessmentItemRef itemRef:section.getAssessmentItemRefCollection()) {
                    OpenAssessmentItem assessmentItem = OpenAssessmentItem.createInstance(itemRef.getType());
                    assessmentItem.LoadFromString(questionList.get(itemRef.getIdentifier().toLowerCase()),jcItem);
                    OpenItemResult openItemResult = getResultInstance(assessmentItem, itemRef.getWeight(), sequenceIndex);
                    openItemResultList.add(openItemResult);
                    sequenceIndex++;
                }
            }
        }
        return new OpenAssessmentResult(assessmentTest.getIdentifier(),"0","","","0","","","","0","","0","","0","","0","",assessmentTest.getIdentifier(),DateUtil.dateToXmlDate(new Date()),0,openItemResultList);
    }

    /**
     * 生成作答结果
     * @param openAssessmentItem
     * @param weight
     * @param sequenceIndex
     * @return
     */
    private static OpenItemResult getResultInstance(OpenAssessmentItem openAssessmentItem,Double weight,Integer sequenceIndex){

        XMLGregorianCalendar datestamp = DateUtil.dateToXmlDate(new Date());

        //region OpenResultResponseVariable
        List<OpenResultResponseVariable> responseVariables = new ArrayList<>();
        OpenResultResponseVariable resultResponseVar = new OpenResultResponseVariable("RESPONSE", CardinalityType.SINGLE, BaseTypeType.IDENTIFIER,
                "", "");
        responseVariables.add(resultResponseVar);
        //endregion

        //region OpenScoreOutcomeVariable
        List<OpenScoreOutcomeVariable> outcomeVariables = new ArrayList<>();


        OpenScoreOutcomeVariable outcomeVariable2 = new OpenScoreOutcomeVariable("SCORE", CardinalityType.SINGLE, BaseTypeType.FLOAT,
                weight, 0, false);
        outcomeVariables.add(outcomeVariable2);
        //endregion

        List<OpenScorerCommentsOutcomeVariable> scorerCommentsOutcomeVariables = new ArrayList<>();

        return new OpenItemResult(openAssessmentItem.getIdentifier(), datestamp, sequenceIndex, SessionStatusType.INITIAL,
                1, false, CompletionStatus.NOT_ATTEMPTED, responseVariables, outcomeVariables,
                scorerCommentsOutcomeVariables, 0);

    }

}
